package com.xique.park.service.command.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xique.common.core.constant.Constants;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.park.bean.domain.ParkDeviceNew;
import com.xique.park.service.command.service.ICommandCommService;
import com.xique.park.service.service.IParkDeviceNewService;
import com.xique.park.utils.RedisHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 下发命令公共service
 *
 * @author: xique
 */
@Service
public class CommandCommServiceImpl implements ICommandCommService {

    @Autowired
    private IParkDeviceNewService parkDeviceNewService;

    @Autowired
    private RedisHandler redisHandler;

    /**
     * 命令基本格式封装
     */
    @Override
    public JSONObject getBaseObj(Long parkId, String sn, String serviceName, String version) {
        JSONObject obj = new JSONObject();
        obj.put("mqtt_key", "");
        obj.put("charset", "UTF-8");
        obj.put("service", serviceName);
        obj.put("version", version);
        obj.put("sign", "123456789456");
        obj.put("ts", System.currentTimeMillis() / 1000);
        obj.put("device_code", sn);
        return obj;
    }

    /**
     * 查询车场下的所有主设备
     */
    @Override
    public List<String> getMainDeviceCodesByParkId(Long parkId) {
        ParkDeviceNew parkDeviceNew = new ParkDeviceNew();
        parkDeviceNew.setParkId(parkId);
        parkDeviceNew.setIsMain("Y");
        List<ParkDeviceNew> parkDeviceNewList = parkDeviceNewService.selectParkDeviceNewList(parkDeviceNew);

        List<String> devCodes = new ArrayList<>();
        if (!CollectionUtils.isEmpty(parkDeviceNewList)) {
            devCodes = parkDeviceNewList.stream().map(ParkDeviceNew::getCode).collect(Collectors.toList());
        }
        return devCodes;
    }

    /**
     * 查询通道主设备
     */
    @Override
    public String getMainDeviceCodeByLaneId(Long parkId, Long laneId) {
        ParkDeviceNew parkDeviceNew = new ParkDeviceNew();
        parkDeviceNew.setParkId(parkId);
        parkDeviceNew.setLaneId(laneId);
        parkDeviceNew.setIsMain("Y");
        List<ParkDeviceNew> parkDeviceNewList = parkDeviceNewService.selectParkDeviceNewList(parkDeviceNew);
        if (!CollectionUtils.isEmpty(parkDeviceNewList)) {
            return parkDeviceNewList.get(0).getCode();
        } else {
            return null;
        }
    }

    public List<ParkDeviceNew> getMainDevListByParkId(Long parkId) {
        ParkDeviceNew parkDeviceNew = new ParkDeviceNew();
        parkDeviceNew.setParkId(parkId);
        parkDeviceNew.setIsMain("Y");
        return parkDeviceNewService.selectParkDeviceNewList(parkDeviceNew);
    }

    @Override
    public JSONObject transformRes(AjaxResult res) {
        JSONObject obj = new JSONObject();
        obj.put(Constants.MESSAGE, res.get(Constants.MESSAGE));
        String status = (String) res.get("status");
        if (StringUtils.isNotEmpty(status)) {
            if ("SUCCESS".equals(status)) {
                obj.put("commandStatus", "成功");
            } else {
                obj.put("commandStatus", "失败");
            }
        }
        return obj;
    }

    @Override
    public JSONObject getCommandStatus(String className, List<String> devCodeList, List<Long> recIdList) {
        // 查询车场下全部的相机（单车场的相机数量有限）
        ParkDeviceNew parkDeviceNew = new ParkDeviceNew();
        parkDeviceNew.setParkId(SecurityUtils.getParkId());
        List<ParkDeviceNew> parkDeviceNewList = parkDeviceNewService.selectParkDeviceNewList(parkDeviceNew);
        JSONObject data = redisHandler.getBatchAsyncCommandStatus(className, devCodeList, recIdList);
        JSONObject resObj = new JSONObject();
        if (StringUtils.isNotNull(data)) {
            for (Map.Entry<?, ?> entry : data.entrySet()) {
                JSONObject statusObj = new JSONObject();
                String value = entry.getValue().toString();
                JSONArray jsonArray = JSONArray.parseArray(value);
                int successNum = 0;
                for (int i = 0; i < jsonArray.size(); i++) {
                    // device_code -> f49d281b-7ea1c7b8
                    JSONObject obj = jsonArray.getJSONObject(i);
                    if (StringUtils.isNotEmpty(obj.getString("device_code"))) {
                        ParkDeviceNew device = parkDeviceNewList.stream().filter(e -> obj.getString("device_code").equals(e.getCode())).findAny().orElse(null);
                        if (device != null) {
                            obj.put("device_name", device.getName());
                        }
                    }
                    if (StringUtils.isNotEmpty(obj.getString("status")) && "SUCCESS".equals(obj.getString("status"))) {
                        successNum++;
                    }
                }
                statusObj.put("list", jsonArray);
                statusObj.put("successNum", successNum);
                statusObj.put("totalNum", devCodeList.size());
                resObj.put(entry.getKey().toString(), statusObj);
            }
        }
        resObj.put("class_name", className);
        return resObj;
    }

    @Override
    public JSONObject getCommandStatus(String className, Long parkId, List<Long> recIdList) {
        List<String> devCodeList = getMainDeviceCodesByParkId(parkId);
        return getCommandStatus(className, devCodeList, recIdList);
    }

    @Override
    public JSONObject getCommandStatus(String className, Long laneId, Long recId) {
        String sn = getMainDeviceCodeByLaneId(SecurityUtils.getParkId(), laneId);
        if (StringUtils.isEmpty(sn)) {
            JSONObject resObj = new JSONObject();
            JSONObject statusObj = new JSONObject();
            statusObj.put("successNum", 0);
            statusObj.put("totalNum", 0);
            resObj.put(recId.toString(), statusObj);
            return resObj;
        }
        List<Long> recIdList = new ArrayList<>(1);
        recIdList.add(recId);
        List<String> devCodeList = new ArrayList<>(1);
        devCodeList.add(sn);
        return getCommandStatus(className, devCodeList, recIdList);
    }

}
